#include "video.h"
#include "ui_video.h"
#include <QMessageBox>
#include <QDebug>
#include <QFileDialog>
#include <QDateTime>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

VideoWidget::VideoWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VideoWidget),
    serverPort(8080),
    isReceiving(false),
    isStreaming(false),
        savePath("C:\\Users\\ss66\\Desktop\\HQ_ending\\Qt"),  // 设置你的默认路径
        m_fileIndex(1)
    {
        ui->setupUi(this);

        setWindowTitle("UDP图像接收与OpenCV处理");

    udpSocket = new QUdpSocket(this);
    connect(udpSocket, &QUdpSocket::readyRead, this, &VideoWidget::readPendingDatagrams);

    processTimer = new QTimer(this);
    connect(processTimer, &QTimer::timeout, this, &VideoWidget::processAndDisplayImage);

    // 加载分类器
    if (!eyeClassifier.load("F:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_eye.xml")) {
        QMessageBox::critical(this, "错误", "无法加载眼睛检测分类器");
    }

    if (!faceClassifier.load("F:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml")) {
        QMessageBox::critical(this, "错误", "无法加载脸部检测分类器");
    }

    ui->statusLabel->setText("就绪");
    ui->serverIpEdit->setText("192.168.31.233");
    ui->serverPortEdit->setText("8888");
    ui->stopBtn->setEnabled(false);
    ui->saveBtn->setEnabled(true);  // 保持手动保存功能可用
}

// 新增：设置保存路径的接口（可在外部调用，例如通过按钮设置）
void VideoWidget::setSavePath(const QString &path) {
    savePath = path;
    // 自动创建目录（如果不存在）
    QDir dir(savePath);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
}

VideoWidget::~VideoWidget()
{
    delete ui;
}

void VideoWidget::on_startBtn_clicked()
{
    serverAddress.setAddress(ui->serverIpEdit->text());
    serverPort = ui->serverPortEdit->text().toUShort();

    if (udpSocket->bind(QHostAddress::Any, quint16(0), QUdpSocket::DefaultForPlatform)) {
        ui->statusLabel->setText("已连接到服务器，正在请求图像流...");
        ui->startBtn->setEnabled(false);
        ui->stopBtn->setEnabled(true);
        isReceiving = true;
        processTimer->start(30);
        QByteArray request("get_photo");
        udpSocket->writeDatagram(request, serverAddress, serverPort);
        isStreaming = true;
    } else {
        QMessageBox::critical(this, "错误", "无法绑定UDP套接字");
        ui->statusLabel->setText("连接失败");
    }
}

void VideoWidget::on_stopBtn_clicked()
{
    if (isStreaming) {
        QByteArray request("stop_get_photo");
        udpSocket->writeDatagram(request, serverAddress, serverPort);
        isStreaming = false;
    }

    isReceiving = false;
    processTimer->stop();
    udpSocket->close();
    ui->statusLabel->setText("已断开连接");
    ui->startBtn->setEnabled(true);
    ui->stopBtn->setEnabled(false);
    ui->saveBtn->setEnabled(false);
}

void VideoWidget::on_saveBtn_clicked()
{
    // 手动保存
    if (imageData.isEmpty()) {
        ui->statusLabel->setText("没有可保存的图像");
        return;
    }

    QString fileName = QFileDialog::getSaveFileName(
        this, tr("保存图像"), savePath, tr("JPEG Image (*.jpg);;PNG Image (*.png)")
    );

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly)) {
            file.write(imageData);
            file.close();
            ui->statusLabel->setText("图像已保存: " + fileName);
        } else {
            ui->statusLabel->setText("无法保存图像: " + file.errorString());
        }
    }
}

void VideoWidget::readPendingDatagrams()
{
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(), datagram.size());
        imageData = datagram;
        qDebug() << "收到数据：" << datagram.size() << "字节";
    }
}

// 新增：生成随机文件名（基于时间戳+随机数）
QString VideoWidget::generateRandomFileName() {
    // 格式：01.jpg、02.jpg...10.jpg...（不足2位补0）
    QString fileName = QString("%1.jpg").arg(m_fileIndex++, 2, 10, QChar('0'));
    return fileName;
}

// 新增：自动保存图片函数
void VideoWidget::autoSaveImage(const Mat &frame) {
    if (savePath.isEmpty()) {
        ui->statusLabel->setText("未设置保存路径，自动保存失败");
        return;
    }

    // 创建完整文件路径
    QString fullPath = savePath + generateRandomFileName();

    // 保存OpenCV处理后的图像（避免原始数据可能的格式问题）
    vector<uchar> buffer;
    imencode(".jpg", frame, buffer);  // 重新编码为JPG格式
    QByteArray imgData(reinterpret_cast<const char*>(buffer.data()), buffer.size());

    QFile file(fullPath);
    if (file.open(QIODevice::WriteOnly)) {
        file.write(imgData);
        file.close();
        ui->statusLabel->setText(QString("检测到3人及以上，已保存：%1").arg(fullPath));
        qDebug() << "自动保存成功：" << fullPath;
    } else {
        ui->statusLabel->setText(QString("自动保存失败：%1").arg(file.errorString()));
    }
}

void VideoWidget::processAndDisplayImage()
{
    if (imageData.isEmpty()) return;

    vector<uchar> buffer(imageData.begin(), imageData.end());
    Mat frame = imdecode(buffer, IMREAD_COLOR);
    if (frame.empty()) {
        ui->statusLabel->setText("图像解码失败");
        return;
    }

    // 人脸检测
    Mat gray;
    cvtColor(frame, gray, COLOR_BGR2GRAY);
    vector<Rect> faces;
    faceClassifier.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));

    int eyesTotal = 0;
    for (size_t i = 0; i < faces.size(); i++) {
        rectangle(frame, faces[i], Scalar(255, 0, 0), 2);
        Mat faceROI = gray(faces[i]);
        vector<Rect> faceEyes;
        eyeClassifier.detectMultiScale(faceROI, faceEyes, 1.1, 2, 0, Size(30, 30));
        eyesTotal += faceEyes.size();

        // 绘制眼睛矩形
        for (size_t j = 0; j < faceEyes.size(); j++) {
            int x = faces[i].x + faceEyes[j].x;
            int y = faces[i].y + faceEyes[j].y;
            rectangle(frame, Rect(x, y, faceEyes[j].width, faceEyes[j].height), Scalar(0, 255, 0), 2);
        }
    }

    // 新增：判断是否需要自动保存（3人及以上）
    if (faces.size() >= 3) {
        autoSaveImage(frame);  // 传入当前处理的帧用于保存
    }

    // 更新状态标签
    ui->statusLabel->setText(QString("检测到 %1 张人脸，%2 只眼睛").arg(faces.size()).arg(eyesTotal));

    // 转换为QImage显示
    cvtColor(frame, frame, COLOR_BGR2RGB);
    QImage qImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
    ui->imageLabel->setPixmap(QPixmap::fromImage(qImage).scaled(
        ui->imageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
